Skip to content

Return default values for unset optional fields instead of throwing#2

Merged
merlimat merged 1 commit intomasterfrom
fix-optional-field-defaults
Mar 17, 2026
Merged

Return default values for unset optional fields instead of throwing#2
merlimat merged 1 commit intomasterfrom
fix-optional-field-defaults

Conversation

@merlimat
Copy link
Collaborator

Summary

  • Optional fields now return type-appropriate default values when not set, matching standard Protobuf behavior
  • Only required fields throw IllegalStateException when accessed unset
  • Fixed clear() to properly reset all field types (numbers, booleans, enums, strings, bytes, messages) back to defaults

Motivation

Code that works with standard Protobuf relies on optional field getters returning default values (0, false, "", empty bytes, first enum value, default message instance). LightProto was throwing IllegalStateException instead, breaking compatibility.

Changes

Code generator (6 files):

  • LightProtoNumberField / LightProtoBooleanField / LightProtoEnumField: Changed throw condition from !hasImplicitPresence && !isDefaultValueSet to isRequired(); fixed clear() to always reset
  • LightProtoStringField: Required fields throw; implicit presence uses bufferLen check; optional without default returns ""
  • LightProtoBytesField: Required fields throw; all others return empty bytes/buffer
  • LightProtoMessageField: Required fields throw; optional fields lazily create an empty instance

Tests (5 files, 10 new tests):

  • Unset optional field access: numbers, strings, bytes, messages (including nested sub-messages)
  • clear() resets: all number types, strings, bytes, sub-messages, proto3 fields
  • Wire-format verification against protobuf-java after clear

Test plan

  • All 199 tests pass (189 existing + 10 new)
  • Verified unset optional field access returns defaults for all types
  • Verified clear() resets values (not just presence bits) for all types
  • Verified sub-message getter returns empty instance without setting presence
  • Verified serialization compatibility with protobuf-java after clear

Previously, accessing an unset optional field (proto2) would throw
IllegalStateException. This breaks compatibility with standard Protobuf,
which returns type-appropriate default values (0, false, "", empty bytes,
first enum value, empty message instance).

Now only required fields throw IllegalStateException when not set.
Optional fields return defaults matching Protobuf behavior:
- Numbers: 0 / 0L / 0.0 / 0.0f
- Booleans: false
- Strings: ""
- Bytes: empty byte[] / empty ByteBuf
- Enums: valueOf(0)
- Messages: lazily-created empty instance

Also fixed clear() to properly reset all field types to defaults.
@merlimat merlimat merged commit 4f92b7d into master Mar 17, 2026
1 check passed
@merlimat merlimat deleted the fix-optional-field-defaults branch March 17, 2026 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant